﻿namespace Spectral.Operations
{
    using System;

    /// <summary>
    /// Provides methods for generic arithmetic.
    /// </summary>
    public static class Operator
    {
        /// <summary>
        /// Gets a number initialized with zero.
        /// </summary>
        /// <typeparam name="T">The type of number to be returned.</typeparam>
        /// <returns>A number initialized with zero.</returns>
        public static T Zero<T>()
            where T : struct, IEquatable<T>, IComparable<T>
        {
            return Operator<T>.Zero;
        }

        /// <summary>
        /// Gets a number initialized with one.
        /// </summary>
        /// <typeparam name="T">The type of number to be returned.</typeparam>
        /// <returns>A number initialized with one.</returns>
        public static T One<T>()
            where T : struct, IEquatable<T>, IComparable<T>
        {
            return Operator<T>.One;
        }

        /// <summary>
        /// Adds two numbers together.
        /// </summary>
        /// <typeparam name="T">The type of number to be returned.</typeparam>
        /// <param name="left">The left side of the operation.</param>
        /// <param name="right">The right side of the operation.</param>
        /// <returns>The result of the operation.</returns>
        public static T Add<T>(this T left, T right)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            return Operator<T>.Add(left, right);
        }

        /// <summary>
        /// Subtracts one number from another.
        /// </summary>
        /// <typeparam name="T">The type of number to be returned.</typeparam>
        /// <param name="left">The left side of the operation.</param>
        /// <param name="right">The right side of the operation.</param>
        /// <returns>The result of the operation.</returns>
        public static T Subtract<T>(this T left, T right)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            return Operator<T>.Subtract(left, right);
        }

        /// <summary>
        /// Multiplies two numbers together.
        /// </summary>
        /// <typeparam name="T">The type of number to be returned.</typeparam>
        /// <param name="left">The left side of the operation.</param>
        /// <param name="right">The right side of the operation.</param>
        /// <returns>The result of the operation.</returns>
        public static T Multiply<T>(this T left, T right)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            return Operator<T>.Multiply(left, right);
        }

        /// <summary>
        /// Divides one number into another.
        /// </summary>
        /// <typeparam name="T">The type of number to be returned.</typeparam>
        /// <param name="left">The left side of the operation.</param>
        /// <param name="right">The right side of the operation.</param>
        /// <returns>The result of the operation.</returns>
        public static T Divide<T>(this T left, T right)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            return Operator<T>.Divide(left, right);
        }

        /// <summary>
        /// Finds the remainder of a division operation.
        /// </summary>
        /// <typeparam name="T">The type of number to be returned.</typeparam>
        /// <param name="left">The left side of the operation.</param>
        /// <param name="right">The right side of the operation.</param>
        /// <returns>The result of the operation.</returns>
        public static T Remainder<T>(this T left, T right)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            return Operator<T>.Remainder(left, right);
        }

        /// <summary>
        /// Negates the specified value.
        /// </summary>
        /// <typeparam name="T">The type of number to be returned.</typeparam>
        /// <param name="value">The value.</param>
        /// <returns>The result of the operation.</returns>
        public static T Negate<T>(this T value)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            return Operator<T>.Negate(value);
        }

        /// <summary>
        /// Finds the sqare root of the specified value.
        /// </summary>
        /// <typeparam name="T">The type of number to be returned.</typeparam>
        /// <param name="value">The value.</param>
        /// <returns>The result of the operation.</returns>
        public static T Sqrt<T>(this T value)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            return Operator<T>.Sqrt(value);
        }

        /// <summary>
        /// Raises a value to the specified power.
        /// </summary>
        /// <typeparam name="T">The type of number to be returned.</typeparam>
        /// <param name="value">The base.</param>
        /// <param name="power">The power.</param>
        /// <returns>The result of the operation.</returns>
        public static T Pow<T>(this T value, T power)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            return Operator<T>.Pow(value, power);
        }

        /// <summary>
        /// Rounds to the largest integer less than the specified value.
        /// </summary>
        /// <typeparam name="T">The type of number to be returned.</typeparam>
        /// <param name="value">The value.</param>
        /// <returns>The result of the operation.</returns>
        public static T Floor<T>(this T value)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            return Operator<T>.Sqrt(value);
        }

        /// <summary>
        /// Rounds to the smallest integer greater than the specified value.
        /// </summary>
        /// <typeparam name="T">The type of number to be returned.</typeparam>
        /// <param name="value">The value.</param>
        /// <returns>The result of the operation.</returns>
        public static T Ceiling<T>(this T value)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            return Operator<T>.Sqrt(value);
        }

        /// <summary>
        /// Calculates the sine of the specified value.
        /// </summary>
        /// <typeparam name="T">The type of number to be returned.</typeparam>
        /// <param name="value">The value.</param>
        /// <returns>The result of the operation.</returns>
        public static T Sin<T>(this T value)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            return Operator<T>.Sin(value);
        }

        /// <summary>
        /// Calculates the cosine of the specified value.
        /// </summary>
        /// <typeparam name="T">The type of number to be returned.</typeparam>
        /// <param name="value">The value.</param>
        /// <returns>The result of the operation.</returns>
        public static T Cos<T>(this T value)
            where T : struct, IEquatable<T>, IComparable<T>
        {
            return Operator<T>.Cos(value);
        }
    }
}
